/*****************************************************************************
 *
 * Copyright (C) 2003 CSHCN, University of Maryland.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * Authors: Dionysus Blazakis <dblaze@umd.edu>
 *          Jonathan Polley <jpolley@umd.edu>
 *          Dan Rusk <drusk@umd.edu>
 *          Manish Karir <karir@umd.edu>
 *          Jonathan McGee <mcgee@umd.edu>
 *
 *****************************************************************************/

#ifndef MULTICAST_ROUTING_TABLE_H
#define MULTICAST_ROUTING_TABLE_H

#ifndef NS_NO_GLOBALS
#include "defs.h"

typedef struct mrt_table mrt_table_t;

#define MRT_UPSTREAM   1
#define MRT_DOWNSTREAM 2

/* struct for next hops */
typedef struct _mrt_nexthop_t {
    u_int32_t addr;
    u_int8_t activated;
    u_int8_t direction;
    u_int8_t grp_hcnt;              /* only for use with upstream hops */
    u_int32_t grp_seqno;            /* only for use with upstream hops */
    struct _mrt_nexthop_t *next;
} mrt_nexthop_t;

typedef struct _mrt_src_t {
    u_int32_t src_addr;
    struct _mrt_src_t *next;
} mrt_src_t;

typedef struct _mrt_orig_t {
    u_int32_t orig_addr;
    u_int32_t grp_seqno;
    u_int8_t grp_hcnt;
    struct timer cleanup_timer;

    mrt_table_t * up;
    struct _mrt_orig_t * next;
} mrt_orig_t;

/* Route table entries */
struct mrt_table {
    u_int32_t grp_addr;
    u_int32_t grp_leader_addr;
    u_int32_t grp_seqno;
    u_int8_t am_leader;            /* are we the group leader? */

    unsigned int ifindex;
    u_int8_t leader_hcnt;
    u_int8_t is_member;
    u_int8_t is_router;
    u_int8_t is_broken;
    u_int8_t in_repair;
    u_int8_t is_gateway;

    struct timer mrt_timer;
    struct timer grph_timer;
    struct timer mact_timer;     /* send mact to our upstream */
    struct timer prune_timer;

    mrt_nexthop_t *nexthops;
    u_int8_t activated_upstream_cnt;
    u_int16_t activated_downstream_cnt;

    mrt_src_t * sources;
    mrt_orig_t * origlist;

    char grph_update_cnt;  /* for if the next grph is to be an update */

    struct mrt_table *next;
};


#define MRT_TABLESIZE 64		/* Must be a power of 2 */
#define MRT_TABLEMASK (MRT_TABLESIZE - 1)

struct multicast_routing_table {
    unsigned int num_entries;
    mrt_table_t *tbl[MRT_TABLESIZE];
};

#endif				/* NS_NO_GLOBALS */

#ifndef NS_NO_DECLARATIONS

extern struct multicast_routing_table mrt_tbl;

void mrt_table_init();
void mrt_table_destroy();
mrt_table_t *mrt_table_insert(u_int32_t grp_addr, u_int32_t grp_leader_addr,
                              u_int32_t grp_seqno,
                              unsigned int ifindex,
                              u_int8_t leader_hcnt,
                              u_int8_t is_member);

NS_INLINE mrt_table_t *mrt_table_update_timeout(mrt_table_t * mrt,
					      u_int32_t lifetime);
mrt_table_t *mrt_table_find(u_int32_t grp_addr);
void mrt_table_delete(u_int32_t grp_addr);
mrt_nexthop_t *mrt_table_get_activated_upstream(mrt_table_t * mrt);
mrt_nexthop_t *mrt_table_get_best_upstream(mrt_table_t *mrt);

mrt_nexthop_t *mrt_nexthop_add(mrt_table_t * mrt, u_int32_t addr, 
    u_int8_t direction, u_int32_t grp_seqno);
void mrt_nexthop_remove(mrt_table_t * mrt, u_int32_t addr );
void mrt_nexthop_activate(mrt_table_t * mrt, u_int32_t addr);
void mrt_nexthop_deactivate(mrt_table_t * mrt, u_int32_t addr);
void mrt_nexthop_remove_all(mrt_table_t * mrt);
mrt_nexthop_t *mrt_nexthop_find(mrt_table_t *mrt, uint32_t addr);

mrt_src_t *mrt_sources_find(mrt_table_t * mrt, u_int32_t src);
void mrt_sources_add(u_int32_t src, u_int32_t dest);
void mrt_sources_remove_all(mrt_table_t * mrt);

mrt_orig_t * mrt_origlist_find(mrt_table_t *mrt, u_int32_t orig);
mrt_orig_t * mrt_origlist_add(mrt_table_t *mrt, u_int32_t orig);
void mrt_origlist_remove(mrt_orig_t *entry);

void mrt_table_set_leader(mrt_table_t * mrt, u_int32_t grp_leader_addr, u_int8_t leader_hcnt);
void mrt_table_set_leader_hopcount(mrt_table_t * mrt, u_int8_t leader_hcnt);
void mrt_table_become_leader(mrt_table_t *mrt);

void mrt_table_set_membership(mrt_table_t * mrt, u_int8_t ismember);
void mrt_table_start_routing(mrt_table_t *mrt);
void mrt_table_stop_routing(mrt_table_t *mrt);

void mrt_table_dump(void);

#endif				/* NS_NO_DECLARATIONS */

#endif				/* MULTICAST_ROUTING_TABLE_H */
